package com.kongjs.application.filter;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class IpFilter extends OncePerRequestFilter {

    static {
        List<ParamFlowRule> rules = new ArrayList<>();
        ParamFlowRule rule = new ParamFlowRule();
        rule.setResource("ip_limit");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setParamIdx(0);
        rule.setCount(10); // 设置为每秒10个请求
        rule.setDurationInSec(1); // 设置统计窗口为1秒

        // 添加白名单IP例外项 - 允许无限访问
        List<ParamFlowItem> items = new ArrayList<>();
        ParamFlowItem whiteListItem = new ParamFlowItem();
        whiteListItem.setObject("127.0.0.1");  // 示例白名单IP
        whiteListItem.setClassType(String.class.getName());
        whiteListItem.setCount(100);  // 非常大的值表示不限流
        items.add(whiteListItem);

        // 添加黑名单IP例外项 - 禁止访问
        ParamFlowItem blackListItem = new ParamFlowItem();
        blackListItem.setObject("192.168.1.100");  // 示例黑名单IP
        blackListItem.setClassType(String.class.getName());
        blackListItem.setCount(0);  // 0表示禁止访问
        items.add(blackListItem);

        rule.setParamFlowItemList(items);

        rules.add(rule);
        ParamFlowRuleManager.loadRules(rules);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String ip = request.getRemoteAddr();
        log.info("访问 ip {}",ip);
        try (Entry entry = SphU.entry("ip_limit", EntryType.IN, 1, ip)) {
            filterChain.doFilter(request, response);
        } catch (BlockException e) {
            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            log.error("ip {} {}", ip, e.getMessage());
        }
    }
}
